
`ifndef PLL_DEF
`define PLL_DEF(a,b,c)
`endif

`ifndef PLL_RV_DEF
`define PLL_RV_DEF
`endif

/*
综合项目
af_run.tcl
slave_ahb.asf
slave_ahb.sdc
slave_ahb.v

yosys -p "read_verilog ../def.v top.v ./../core.v" -p "synth_intel -family cycloneive -top slave_ahb -iopads" -p "write_verilog -simple-lhs -attr2comment -defparam -nohex -renameprefix syn_ top.vqm"

F:\BaiduNetdiskDownload\Supra-2023.02.b0-7773ca8a-win64-all\bin\af.exe -B --batch --mode SYNPLICITY -X "set QUARTUS_SDC true" -X "set FITTING timing_more" -X "set FITTER hybrid" -X "set EFFORT highest" -X "set HOLDX default" -X "set SKEW basic"

*/

/*
slave_ahb 时序
CLK         :___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^...___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___^^^___
CTR         :___/NSEQ |BUSY | SEQ |--------------------------------------------...---------------------------------------------------------------       ;注:可忽略BUSY与SEQ
HSEL        :___^^^^^^^^^^^^^^^^^^^--------------------------------------------...---------------------------------------------------------------
ROMSEL      :___^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___________________________________________________________
DAT1        :--\______________________________________________________________/-----------------------------------------------------------
COUNTER     :---------| 0          _____|1    |2    |3    |4....|6   |7   |>8(正确) if(ahb_read_counter<9) ahb_read_dat <= slave_ahb_hrdata;
HREADYOUT   :^^^^^^^^^______________________________________...._____/^^^^|此时读取为正确,在7的时候,上升沿判断是低电平.但持续为高电平 (可能是SEQ时开始低电平)
HREADYOUT   :         |--------等待约6个周期?      ----------...------|注:应该约为6个周期,可能是SEQ时开始低电平. 但在`PLL_DEF("8.0",8'd42,8'd42);(112MHz?) 下,低电平持续50~60ns?

*/


`define AHB_IDLE   2'b00
`define AHB_BUSY   2'b01
`define AHB_NONSEQ 2'b10
`define AHB_SEQ    2'b11

module slave_ahb (
    test_pin,
    OSC32_IN,
    OSC32_OUT,
    PIN_OSC,
    PIN_OSC_OUT,
    PIN_HSE,
    PIN_HSI,
    test_in_pin,
);
    output wire[4:0] test_pin;
    input wire PIN_HSE;
    input wire PIN_HSI;
    input wire OSC32_IN;
    input wire OSC32_OUT;
    input wire PIN_OSC;
    output wire PIN_OSC_OUT;
    input wire test_in_pin;

    assign PIN_OSC_OUT = PIN_HSI;

    //120MHz
    //`PLL_DEF("12.0",8'd30,8'd30);

    //164MHz
    `PLL_DEF("12.0",8'd40,8'd40);

    //196MHz
    //`PLL_DEF("12.0",8'd50,8'd50);

    wire sys_gck;
    assign test_pin[0] = PIN_HSI;
    assign test_pin[1] = test_in_pin;
    assign test_pin[2] = OSC32_OUT;
    assign test_pin[3] = PIN_OSC;

    reg         slave_ahb_hsel = 1'b0;
    reg         slave_ahb_hready = 1'b1;
    wire        slave_ahb_hreadyout;
    reg[1:0]    slave_ahb_htrans = `AHB_IDLE;
    reg[2:0]    slave_ahb_hsize = 3'd0;
    reg[2:0]    slave_ahb_hburst = 3'd0;
    reg         slave_ahb_hwrite = 1'b0;
    reg[31:0]   slave_ahb_haddr = 32'h20000000;
    reg[31:0]   slave_ahb_hwdata = 32'd0;
    wire        slave_ahb_hresp;
    wire[31:0]  slave_ahb_hrdata;

    reg [7:0] gpio4_io_in = 0;
    wire[7:0] gpio4_io_out_data;
    wire[7:0] gpio4_io_out_en;

    reg [7:0] gpio5_io_in = 0;
    wire[7:0] gpio5_io_out_data;
    wire[7:0] gpio5_io_out_en;

    reg [7:0] gpio6_io_in = 0;
    wire[7:0] gpio6_io_out_data;
    wire[7:0] gpio6_io_out_en;

    reg [7:0] gpio7_io_in = 0;
    wire[7:0] gpio7_io_out_data;
    wire[7:0] gpio7_io_out_en;

    alta_rv32 rv32(
        `PLL_RV_DEF

  /*input        */ .slave_ahb_hsel     (slave_ahb_hsel     ) ,       //当FPGA需要访问AHB时
  /*input        */ .slave_ahb_hready   (slave_ahb_hready   ) ,       //1'b1
  /*output       */ .slave_ahb_hreadyout(slave_ahb_hreadyout) ,       //AHB需要在hreadyout,才能进行操作,否则将错误,(调试接口失败?)
  /*input  [1:0] */ .slave_ahb_htrans   (slave_ahb_htrans   ) ,       //0:idle,1:busy,2:nonseq,3:seq
  /*input  [2:0] */ .slave_ahb_hsize    (slave_ahb_hsize    ) ,        //0:8bit,1:16bit,2:32bit,3:64,...
  /*input  [2:0] */ .slave_ahb_hburst   (slave_ahb_hburst   ) ,       //0:单笔数据,1:不定长批量传输,2:4数据环绕,3:4数据递增,4:8数据环绕,5:8数据递增....
  /*input        */ .slave_ahb_hwrite   (slave_ahb_hwrite   ) ,       //写操作
  /*input  [31:0]*/ .slave_ahb_haddr    (slave_ahb_haddr    ) ,        //地址
  /*input  [31:0]*/ .slave_ahb_hwdata   (slave_ahb_hwdata   ) ,       //写数据
  /*output       */ .slave_ahb_hresp    (slave_ahb_hresp    ) ,        //AHB反馈
  /*output [31:0]*/ .slave_ahb_hrdata   (slave_ahb_hrdata   ) ,       //读数据

    /*input  [7:0]*/ .gpio5_io_in        (gpio5_io_in      ),
    /*output [7:0]*/ .gpio5_io_out_data  (gpio5_io_out_data),
    /*output [7:0]*/ .gpio5_io_out_en    (gpio5_io_out_en  ),

    /*input  [7:0]*/ .gpio6_io_in        (gpio6_io_in      ),
    /*output [7:0]*/ .gpio6_io_out_data  (gpio6_io_out_data),
    /*output [7:0]*/ .gpio6_io_out_en    (gpio6_io_out_en  ),

    /*input  [7:0]*/ .gpio7_io_in        (gpio7_io_in      ),
    /*output [7:0]*/ .gpio7_io_out_data  (gpio7_io_out_data),
    /*output [7:0]*/ .gpio7_io_out_en    (gpio7_io_out_en  ),

    /*input  [7:0]*/ .gpio4_io_in        (gpio4_io_in      ),
    /*output [7:0]*/ .gpio4_io_out_data  (gpio4_io_out_data),
    /*output [7:0]*/ .gpio4_io_out_en    (gpio4_io_out_en  )
    );

    reg trig_read = 1'd0;
    reg wait_read_pre = 1'b0;
    reg wait_read = 1'b0;
    reg wait_read2 = 1'b0;
    always @(posedge sys_gck) begin
        if(slave_ahb_hsel)begin
            //处理读取
            wait_read <= wait_read_pre;
            wait_read_pre <= 1'b0;
            case (slave_ahb_htrans)
                /*
                ahb_htrans
                    可以从 NONSEQ->BUSY->SEQ->(hsel=0)
                    也可以 NONSEQ->SEQ->(hsel=0)
                    也可以 NONSEQ->(hsel=0)
                */
                /*可以省略BUSY*/
                //`AHB_NONSEQ:slave_ahb_htrans <= `AHB_BUSY;
                // `AHB_NONSEQ:slave_ahb_htrans <= `AHB_SEQ;
                // `AHB_BUSY  :slave_ahb_htrans <= `AHB_SEQ;
                // `AHB_SEQ   :slave_ahb_hsel <= 1'b0;
                `AHB_NONSEQ:slave_ahb_hsel <= 1'b0;
                default:;
            endcase
            gpio6_io_in <= gpio6_io_in + 8'd1;
        end
        //else
        if(wait_read)begin
            //等待读取数据
            gpio6_io_in <= gpio6_io_in + 8'd1;
            if(slave_ahb_hreadyout)begin
                wait_read   <= 1'b0;
                gpio5_io_in <= slave_ahb_hrdata[7:0] | 8'h80;
            end

            //处理第二个读取
            if(gpio4_io_out_data[1]&~wait_read2)begin
                slave_ahb_hsel   <= 1'b1;
                slave_ahb_hsize  <= 3'b10;
                slave_ahb_hburst <= 3'b000;
                slave_ahb_haddr  <= 32'h20000004;
                wait_read2       <= 1'b1;
            end
        end
        else if(wait_read2)begin
            if(slave_ahb_hreadyout)begin
                wait_read2 <= 1'b0;
                gpio7_io_in <= slave_ahb_hrdata[7:0];
            end
        end
        else if(gpio4_io_out_data[0]&gpio4_io_out_en[0])begin
            if(~trig_read)begin
                //触发一次读取
                trig_read <= 1'b1;

                wait_read_pre    <= 1'b1;

                slave_ahb_haddr  <= 32'h20000000;
                slave_ahb_hsel   <= 1'b1;
                slave_ahb_hwrite <= 1'b0;
                slave_ahb_hsize  <= 3'b10;
                slave_ahb_htrans <= `AHB_NONSEQ;
                slave_ahb_hburst <= 3'b000;
            end
        end
        else begin
            slave_ahb_hsel <= 1'b0;
            trig_read <= 1'b0;
            wait_read <= 1'b0;
            gpio6_io_in <= 8'd0;
        end

    end



endmodule
